﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using FellowshipOne.API;
using FellowshipOne.API.Base;
using FellowshipOne.API.Base.Interfaces;
using FellowshipOne.API.Events.Model;
using FellowshipOne.API.Events.QueryObject;
using FellowshipOne.API.Realms;
using MasVida.WebApi.Controllers;
using MasVida.WebApi.Models.DataObject;
using MasVida.WebApi.Models.Requests;
using MasVida.WebApi.Models.Responses;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Newtonsoft.Json.Linq;
using Shouldly;

namespace MasVida.WebApi.Tests.Controllers
{
    [TestClass]
    public class AttendanceSummaryControllerTests
    {

        [TestMethod]
        public void GetAttendanceSummariesByGroup()
        {
            // Variables
            const int contextType = 1, groupId = 987;
            AttendanceSummaryRequest groupRequest = new AttendanceSummaryRequest()
            {
                AccessTicket = new F1OAuthTicket(), GroupId = groupId,
                StartDate = DateTime.Today.AddDays(-5),
                EndDate = DateTime.Today
            };

            Mock<IApiSet<AttendanceSummary>> attendanceSummaryMock = new Mock<IApiSet<AttendanceSummary>>();
            JObject jObject = JObject.FromObject(groupRequest);
            var list = new List<AttendanceSummary>()
            {
                new AttendanceSummary() {StartDateTime = DateTime.Today.AddDays(-2)},
                new AttendanceSummary() {StartDateTime = DateTime.Today.AddDays(-10)}
            };
            attendanceSummaryMock.Setup(a => a.Search<AttendanceSummaryCollection>(It.Is<AttendanceSummaryQO>(q => q.AttendanceContextTypeId == contextType && q.AttendanceContextValueId == groupId)))
                .Returns(new AttendanceSummaryCollection(list));
            IRestClient restClient = GetRestClient(attendanceSummaryMock);

            AttendanceSummaryController controller = new AttendanceSummaryController(restClient);

            AttendanceSummaryResponse groupsResponse = controller.GetAttendanceSummaryByGroup(jObject);

            // Assertions
            attendanceSummaryMock.Verify(a => a.Search<AttendanceSummaryCollection>(It.IsAny<AttendanceSummaryQO>()), "Search was not performed");
            groupsResponse.ShouldNotBe(null);
            groupsResponse.Success.ShouldBe(true, "Method should be successfull");
            groupsResponse.AttendanceSummaries.ToList().Count.ShouldBe(1, "There should be 1 attendace Summary retrieved");
        }

        [TestMethod]
        public void UpdateAttendanceSummary()
        {
            AttendanceSummaryDO expectedAttendanceSummaryDo = new AttendanceSummaryDO()
            {
                AttendanceSummaryId = 654,
                IsPosted = true,
                Met = true,
                PresentCount = 54,
                AbsentCount = 0,
                TotalCount = 54
            };
            AttendanceSummaryRequest attendanceSummaryRequest = new AttendanceSummaryRequest()
            {
                AccessTicket = new F1OAuthTicket(),
                AttendanceSummary = expectedAttendanceSummaryDo
            };
            Mock<IApiSet<AttendanceSummary>> attendanceSummaryMock = new Mock<IApiSet<AttendanceSummary>>();
            attendanceSummaryMock.Setup(a => a.Update(It.Is<AttendanceSummary>(s => s.ID == expectedAttendanceSummaryDo.AttendanceSummaryId && s.IsPosted && s.Met), It.Is<string>(s => s == expectedAttendanceSummaryDo.AttendanceSummaryId.ToString())));
            AttendanceSummary attendanceSummary = new AttendanceSummary() {ID = expectedAttendanceSummaryDo.AttendanceSummaryId };
            attendanceSummaryMock.Setup(a => a.Get(It.Is<string>(s => s == expectedAttendanceSummaryDo.AttendanceSummaryId.ToString()))).Returns(attendanceSummary);
            IRestClient restClient = GetRestClient(attendanceSummaryMock);
            JObject jObject = JObject.FromObject(attendanceSummaryRequest);
            AttendanceSummaryController controller = new AttendanceSummaryController(restClient);

            AttendanceSummaryResponse groupsResponse = controller.UpdateAttendanceSummary(jObject);

            // Assertions
            attendanceSummaryMock.Verify(a => a.Update(It.IsAny<AttendanceSummary>(), It.IsAny<string>()), "Update was not performed");
            groupsResponse.ShouldNotBe(null);
            groupsResponse.Success.ShouldBe(true, "Method should be successfull");
            attendanceSummary.Met.ShouldBe(expectedAttendanceSummaryDo.Met);
            attendanceSummary.IsPosted.ShouldBe(expectedAttendanceSummaryDo.IsPosted);
            attendanceSummary.PresentCount.ShouldBe(expectedAttendanceSummaryDo.PresentCount);
        }

        [TestMethod]
        public void UpdateAttendanceSummary_ShouldThrowExceptionWhenAbsentGreaterThanCount()
        {
            AttendanceSummaryDO expectedAttendanceSummaryDo = new AttendanceSummaryDO()
            {
                AttendanceSummaryId = 654,
                IsPosted = true,
                Met = true,
                PresentCount = 54,
                AbsentCount = 1,
                TotalCount = 32
            };
            AttendanceSummaryRequest attendanceSummaryRequest = new AttendanceSummaryRequest()
            {
                AccessTicket = new F1OAuthTicket(),
                AttendanceSummary = expectedAttendanceSummaryDo
            };
            Mock<IApiSet<AttendanceSummary>> attendanceSummaryMock = new Mock<IApiSet<AttendanceSummary>>();
            attendanceSummaryMock.Setup(a => a.Update(It.Is<AttendanceSummary>(s => s.ID == expectedAttendanceSummaryDo.AttendanceSummaryId && s.IsPosted && s.Met), It.Is<string>(s => s == expectedAttendanceSummaryDo.AttendanceSummaryId.ToString())));
            AttendanceSummary attendanceSummary = new AttendanceSummary() { ID = expectedAttendanceSummaryDo.AttendanceSummaryId };
            attendanceSummaryMock.Setup(a => a.Get(It.Is<string>(s => s == expectedAttendanceSummaryDo.AttendanceSummaryId.ToString()))).Returns(attendanceSummary);
            IRestClient restClient = GetRestClient(attendanceSummaryMock);
            JObject jObject = JObject.FromObject(attendanceSummaryRequest);
            AttendanceSummaryController controller = new AttendanceSummaryController(restClient);

            AttendanceSummaryResponse groupsResponse = controller.UpdateAttendanceSummary(jObject);

            // Assertions
            groupsResponse.ShouldNotBe(null);
            groupsResponse.Success.ShouldBe(false, "Method should not pass because count is not ok");
        }

        private IRestClient GetRestClient(Mock<IApiSet<AttendanceSummary>> attendanceSummaryMock)
        {
            Mock<IEventsRealm> eventsMock = new Mock<IEventsRealm>();
            eventsMock.Setup(e => e.AttendanceSummary).Returns(attendanceSummaryMock.Object);
            IRestClient restClient = Mock.Of<IRestClient>();
            restClient.EventsRealm = eventsMock.Object;

            return restClient;
        }
    }
}
